package com.yangyang.ralearn.common;

import java.io.Externalizable;
import java.io.IOException;
import java.io.ObjectInput;
import java.io.ObjectOutput;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;

import com.yangyang.ralearn.common.entity.base.ActionLimit;
import com.yangyang.ralearn.common.entity.base.BaseActionModelDef;
import com.yangyang.ralearn.common.entity.base.BasePredicateDef;
import com.yangyang.ralearn.common.entity.base.ParamedPredicate;
import com.yangyang.ralearn.common.types.JObject;
import com.yangyang.ralearn.common.types.JType;

public class JEnvironment implements Externalizable {

	public Map<String, JType> mapNameType = new HashMap<String, JType>();
	public Map<String, BasePredicateDef> mapNamePredicateDef = new HashMap<String, BasePredicateDef>();
	public Map<JType, List<JObject>> mapType2Object = new HashMap<JType, List<JObject>>();
	public Map<String, JObject> mapName2Object = new HashMap<String, JObject>();
	public Map<String, ActionLimit> mapName2ActionLimit = new HashMap<String, ActionLimit>();

	// private static JEnvironment instance = new JEnvironment();

	protected JEnvironment() {
	}

	// public static JEnvironment instance() {
	// return instance;
	// }

	public static JEnvironment newInstance(int id) {
		return new JEnvironment();
	}

	public void clearData() {
		this.mapNameType.clear();
		this.mapNamePredicateDef.clear();
		this.mapType2Object.clear();
		this.mapName2Object.clear();
		this.mapName2ActionLimit.clear();
	}

	/**
	 * 添加物品类型的定义
	 * 
	 * @param line
	 */
	public void addType(String line) {
		Logger.getLogger(JEnvironment.class).debug("addtype:" + line);
		String[] array = line.split("-");
		if (array.length == 1 || array[1].equals("object")
				|| array[1].equals("OBJECT")) {
			array = array[0].split(" ");
			for (String type : array)
				mapNameType.put(type, new JType(type, null));

		} else {
			String parentType = array[1];
			array = array[0].split(" ");
			for (String type : array)
				mapNameType.put(type, new JType(type, parentType));
		}
	}

	/**
	 * 添加谓词的定义
	 * 
	 * @param name
	 * @param parameters
	 */
	public void addPredicateDef(String name, List<String> parameters) {
		List<String> formatedParameters = new ArrayList<String>();
		for (String param : parameters) {
			formatedParameters.add(param.split("-")[1]);
		}
		formatedParameters.add(0, name);
		this.mapNamePredicateDef.put(name, new BasePredicateDef(this,
				formatedParameters.toArray((new String[0]))));
	}

	/**
	 * 添加物品实例
	 * 
	 * @param type
	 * @param objects
	 */
	public void addObjectInstance(String type, List<String> objects) {
		List<JObject> list = this.mapType2Object
				.get(this.mapNameType.get(type));
		if (list == null) {
			list = new ArrayList<JObject>();
			this.mapType2Object.put(this.mapNameType.get(type), list);
		}
		for (String objectName : objects) {
			JObject object = new JObject(type, objectName);
			list.add(object);
			this.mapName2Object.put(objectName, object);
		}

	}

	/**
	 * 添加函数，保留，尚未实现
	 * 
	 * @param name
	 * @param parameters
	 * @param returntype
	 */
	public void addFunctions(String name, List<String> parameters,
			String returntype) {
		System.err.println("function is not supported in version1.0");
	}

	public void print() {
		Logger.getLogger(JEnvironment.class).info(toString());
	}

	@Override
	public String toString() {
		return "JEnvironment [mapNameType=" + mapNameType
				+ ", mapNamePredicateDef=" + mapNamePredicateDef
				+ ", mapType2Object=" + mapType2Object + ", mapName2Object="
				+ mapName2Object + "]";
	}

	@Override
	public void writeExternal(ObjectOutput out) throws IOException {
		// TODO Auto-generated method stub
		out.writeObject(this.mapName2ActionLimit);
		out.writeObject(this.mapName2Object);
		out.writeObject(this.mapNamePredicateDef);
		out.writeObject(this.mapNameType);
		out.writeObject(this.mapType2Object);
	}

	@SuppressWarnings("unchecked")
	@Override
	public void readExternal(ObjectInput in) throws IOException,
			ClassNotFoundException {
		// TODO Auto-generated method stub
		this.mapName2ActionLimit = (Map<String, ActionLimit>) in.readObject();
		this.mapName2Object = (Map<String, JObject>) in.readObject();
		this.mapNamePredicateDef = (Map<String, BasePredicateDef>) in.readObject();
		this.mapNameType = (Map<String, JType>) in.readObject();
		this.mapType2Object = (Map<JType, List<JObject>>) in.readObject();
	}

}
